package main

import (
	"fmt"
)

func main() {
	// receiverIsVal()
	// receiverIsPointer()
	sugarIsVal()
	// sugarIsPointer()
	// methodExpression()
	// methodValue()
}

type A struct {
	tName string
}

func (a A) vName() string {
	fmt.Printf("a.addr:%p\n", &a.tName)
	// 该方法a为值接收者，此处对a.tName字符串修改，实际是在堆上新分配了一段内存空间
	// 但a结构体中tName指向的地址空间并不会被改
	a.tName = "Hi! " + a.tName
	// fmt.Printf("a.addr:%p\n", &a.tName)
	return a.tName
}

func receiverIsVal() {
	a := A{
		tName: "eggo",
	}
	fmt.Println(a.vName())
	fmt.Println(a.tName)
}

func sugarIsVal() {
	a := A{
		tName: "eggo",
	}
	pa := &a
	fmt.Println(pa.vName) // 编译时会优化为 *pa.vName()
}
func (a *A) pName() string {
	// 指针接收者，ret指令执行前会把a结构体中的tName指向新的地址空间，然后栈上才会释放这个函数的栈空间
	a.tName = "Hi! " + a.tName
	return a.tName
}
func receiverIsPointer() {
	a := A{
		tName: "eggo",
	}
	pa := &a
	fmt.Println(pa.pName())
	fmt.Println(a.tName)
}
func sugarIsPointer() {
	a := A{
		tName: "eggo",
	}
	fmt.Println(a.pName()) // 编译时会优化为&a.pName
}

func methodExpression() {
	a := A{tName: "method"}
	f1 := A.vName
	fmt.Println(f1(a)) // 编译器最终优化为A.vName→A.vName(a)
}

func methodValue() {
	a := A{tName: "method"}
	f1 := a.vName
	fmt.Println(f1()) // 编译器最终优化为a.vName→A.vName→A.vName(a)
}
